////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxjpegexifparams.h
/// @brief JPEG EXIF params class
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/// @todo (CAMX-1988) Code clean up apply NC001 coding standard on entire project
/// @todo (CAMX-1989) Code clean up apply GR030 coding standard on entire project

#ifndef CAMXJPEGEXIFPARAMS_H
#define CAMXJPEGEXIFPARAMS_H

#include "camxdefs.h"
#include "camxjpegexifdefs.h"
#include "camxjpeghufftable.h"
#include "camxjpegproperty.h"
#include "camxjpegquanttable.h"
#include "camxjpegutil.h"
#include "camxnode.h"
#include "camxtypes.h"
#include "camxutils.h"

CAMX_NAMESPACE_BEGIN

/// @brief JPEG subsampling
enum class JPEGSubsampling
{
    H2V2,  ///< Format H2V2
    H2V1,  ///< Format H2V1
    H1V2,  ///< Format H1V2
    H1V1,  ///< Format H1V1
};

/// @brief GPS coordinate type
enum class GPSCoordinateType
{
    GPSLATITUDE,   ///< Latitude
    GPSLONGITUDE,  ///< Longitude
    GPSALTITUDE,   ///< Altitude
    GPSMAX,        ///< Max
};

/// @brief EXIF orientation type
enum class EXIFRotationType
{
    EXIF0   = 1,    ///< Rotation angle 0
    EXIF90  = 6,    ///< Rotation angle 90
    EXIF180 = 3,    ///< Rotation angle 180
    EXIF270 = 8,    ///< Rotation angle 270
};

/// @brief EXIF Flash modes
enum class EXIFFlashMode
{
    FLASHON     = 1,   ///< Flash on
    FLASHOFF    = 2,   ///< Flash off
    FLASHAUTO   = 3,   ///< Flash auto
    FLASHMAX,          ///< Flash max
};

/// @brief Image params info
struct EXIFImageParams
{
    ImageFormat      imgFormat;      ///< Image format
    UINT8            numComponents;  ///< Number of components in image
    JPEGSubsampling  subsampling;    ///< subsampling
};

/// @brief GPS data
struct EXIFGPSData
{
    DOUBLE gpsCoordinates[static_cast<UINT32>(GPSCoordinateType::GPSMAX)]; ///< GPS coordinates
    BYTE   gpsProcessingMethod[32];                                        ///< GPS processing method
    INT64  gpsTimeStamp;                                                   ///< GPS time stamp
};

/// @brief EXIF flash data
struct EXIFFlashData
{
    BYTE  flashMode;        ///< Flash mode
    BYTE  flashState;       ///< Flash state
    BYTE  autoExposureMode; ///< Auto exposure mode
};

/// @brief EXIF 3A and sensor data
struct EXIF3ASensorData
{
    FLOAT           aperture;                   ///< Aperture
    FLOAT           focalLength;                ///< Focal length
    INT64           exposureTime;               ///< Exposure time
    INT32           exposureCompensation;       ///< Exposure compensation
    RAT32           exposureCompensationStep;   ///< Exposure compensation step
    INT32           sensitivity;                ///< Sensor sensitivity
    BYTE            whiteBalanceMode;           ///< White balance mode
    INT32           sensitivityBoost;           ///< ControlPostRawSesnsitivityBoost
};

/// @brief EXIF data
struct EXIFData
{
    EXIFGPSData         dataGPS;                    ///< GPS data
    INT32               orientation;                ///< Orientation
    EXIF3ASensorData    data3ASensor;               ///< 3A and sensor data
    EXIFFlashData       dataFlash;                  ///< Flash data
};

static const UINT32 ExifMaxTag              = static_cast<UINT32>(EXIFTagOffset::EXIF_TAG_MAX_OFFSET);
static const UINT32 ExifMaxPropertyLength   = 128;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class for JPEG EXIF Params
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class JPEGEXIFParams
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// JPEGEXIFParams
    ///
    /// @brief  Default constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    JPEGEXIFParams();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~JPEGEXIFParams
    ///
    /// @brief  Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ~JPEGEXIFParams();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Initialize
    ///
    /// @brief  JPEG params initialize
    ///
    /// @param  pNode       pointer to the node
    /// @param  bIsRealTime flag indicating if node is realtime
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult Initialize(
        Node* pNode,
        BOOL  bIsRealTime);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetEXIFImageParams
    ///
    /// @brief  Set image parameters
    ///
    /// @param  imageFormatInfo  Image format
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetEXIFImageParams(
        ImageFormat imageFormatInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetEXIFImageParamsThumb
    ///
    /// @brief  Set thumbnail image parameters
    ///
    /// @param  imageFormatInfo  Image format
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetEXIFImageParamsThumb(
        ImageFormat imageFormatInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetEncodeOutParams
    ///
    /// @brief  Set Encode output params
    ///
    /// @param  pParams  Pointer to encode out params
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE VOID SetEncodeOutParams(
        EncoderOutInfo* pParams)
    {
        m_pEncodeOutParams = pParams;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetEncodeOutParamsThumbnail
    ///
    /// @brief  Set Encode output params for Thumbnail
    ///
    /// @param  pParams  Pointer to encode out params
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE VOID SetEncodeOutParamsThumbnail(
        EncoderOutInfo* pParams)
    {
        m_pEncodeOutParamsThumbnail = pParams;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFData
    ///
    /// @brief  Get EXIF data from meta data
    ///
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetEXIFData();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFImageParams
    ///
    /// @brief  Get image params
    ///
    /// @return Pointer to Image params
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    EXIFImageParams* GetEXIFImageParams();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFImageParamsThumb
    ///
    /// @brief  Get thumbnail image params
    ///
    /// @return Pointer to Image params
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    EXIFImageParams* GetEXIFImageParamsThumb();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFTagInfo
    ///
    /// @brief  Sets the default quantization tabel base on quality
    ///
    /// @return Pointer to Exit tag info data
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    EXIFTagInfo* GetEXIFTagInfo();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetQuantTable
    ///
    /// @brief  Sets the default quantization tabel base on quality
    ///
    /// @param  type        Quantization table type
    /// @param  bThumbnail  if table for thumbnail
    ///
    /// @return Quntization tabel
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    JPEGQuantTable* GetQuantTable(
        QuantTableType type,
        BOOL bThumbnail);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetHuffTable
    ///
    /// @brief  Sets the default Huffman tabel base on quality
    ///
    /// @param  type Huffman table type
    ///
    /// @return Quntization tabel
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    JPEGHuffTable* GetHuffTable(
        HuffTableType type);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEncodeOutParams
    ///
    /// @brief  Set Encode output params
    ///
    /// @return Encoder output param info
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE EncoderOutInfo* GetEncodeOutParams()
    {
        return m_pEncodeOutParams;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEncodeOutParamsThumbnail
    ///
    /// @brief  Set Encode output params for thumbnail
    ///
    /// @return Encoder output param info
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE EncoderOutInfo* GetEncodeOutParamsThumbnail()
    {
        return m_pEncodeOutParamsThumbnail;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetEXIFVendorTags
    ///
    /// @brief  Get EXIF data from meta data
    ///
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetEXIFVendorTags();

private:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetDefaultEXIFTagInfo
    ///
    /// @brief  Sets the default EXIF tags
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetDefaultEXIFTagInfo();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetEXIFTagInfo
    ///
    /// @brief  Sets Exif tag info in EXIF tag array
    ///
    /// @param  tagInfo  Exif tag info to set
    ///
    /// @return Camx result
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetEXIFTagInfo(
        EXIFTagInfo tagInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFDateTime
    ///
    /// @brief  Get EXIF date and time
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFDateTime();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFOrientation
    ///
    /// @brief  Get EXIF orientation
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFOrientation();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFAperture
    ///
    /// @brief  Get lens aperture
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFAperture();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFFocalLength
    ///
    /// @brief  Get lens focal Length
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFFocalLength();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFFocalLengthRational
    ///
    /// @brief  get EXIF focal length rational
    ///
    /// @param  pFocalLength  Pointer to focal length in rational
    /// @param  value         focal length in float
    ///
    /// @return return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetEXIFFocalLengthRational(
        URAT32* pFocalLength,
        FLOAT   value);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFExposureCompensation
    ///
    /// @brief  Get exposure compensation
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFExposureCompensation();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFExposure
    ///
    /// @brief  Get exposure time and shutter speed
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFExposure();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFISO
    ///
    /// @brief  Get ISO sensitivity
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFISO();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFWhiteBalance
    ///
    /// @brief  Get white balance
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFWhiteBalance();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFMeteringMode
    ///
    /// @brief  Get metering mode
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFMeteringMode();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIF3ASensorData
    ///
    /// @brief  Get 3A and sensor data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIF3ASensorData();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFFlashData
    ///
    /// @brief  Get flash data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFFlashData();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetJPEGQualityAndUpdateQuantizationTable
    ///
    /// @brief  Get OEM custom quantization tables if available
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetJPEGQualityAndUpdateQuantizationTable();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetJPEGThumbnailQualityAndUpdateQuantizationTable
    ///
    /// @brief  Get OEM custom quantization tables if available
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetJPEGThumbnailQualityAndUpdateQuantizationTable();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFCustomQuantizationtables
    ///
    /// @brief  Get OEM custom quantization tables if available
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFCustomQuantizationtables();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFGPSProcessingMethod
    ///
    /// @brief  Get GPS processing method
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFGPSProcessingMethod();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ParseGPSCoordinate
    ///
    /// @brief  Parse GPS coordinates
    ///
    /// @param  pCoordinatesStr Pointer to coordinates string
    /// @param  pCoordinates    Pointer to coordinates
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ParseGPSCoordinate(
        const CHAR* pCoordinatesStr,
        URAT32*     pCoordinates);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFLatitude
    ///
    /// @brief  Get GPS Latitude
    ///
    /// @param  value GPS Latitude value in double
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFLatitude(
        DOUBLE value);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFLongitude
    ///
    /// @brief  Get GPS Longitude
    ///
    /// @param  value GPS Longitude value in double
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFLongitude(
        DOUBLE value);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFAltitude
    ///
    /// @brief  Get GPS Altitude
    ///
    /// @param  value GPS Altitude value in double
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFAltitude(
        DOUBLE value);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFGPSCoordinates
    ///
    /// @brief  Get GPS coordinates
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFGPSCoordinates();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFGPSDateTimeStamp
    ///
    /// @brief  Get GPS time stamp
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFGPSDateTimeStamp();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFGPSInfo
    ///
    /// @brief  Get EXIF orientation
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFGPSInfo();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSubsampleCompCount
    ///
    /// @brief  Translate format to get subsampling and component count
    ///
    /// @param  format     Image format
    /// @param  pSS        Pointer to sub sampling
    /// @param  pCompCount Pointer to component count
    ///
    /// @return Camx result
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetSubsampleCompCount(
        Format            format,
        JPEGSubsampling*  pSS,
        UINT8*            pCompCount);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetEXIFImageDimensions
    ///
    /// @brief  Get and set image dimension in EXIF
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetEXIFImageDimensions();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FlushEXIFTagCopyData
    ///
    /// @brief  Flush EXIF copy data
    ///
    /// @param  pEXIFTagData     Pointer to exif tag data
    /// @param  count            Count of exif tags
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID FlushEXIFTagCopyData(
        EXIFTagInfo*  pEXIFTagData,
        UINT32        count);

    JPEGEXIFParams(const JPEGEXIFParams&) = delete;                 ///< Disallow the copy constructor.
    JPEGEXIFParams& operator=(const JPEGEXIFParams&) = delete;      ///< Disallow assignment operator.

    EXIFTagInfo*          m_pEXIFTagData;                           ///< Pointer to EXIF tag data
    EXIFImageParams       m_imageParams;                            ///< Main Image params
    EXIFImageParams       m_imageParamsThumb;                       ///< Main Image params
    JPEGHuffTable*        m_pHuffmanTables;                         ///< Pointer to Huffman tables
    JPEGQuantTable*       m_pQuantTables;                           ///< Pointer to Quantization tables
    JPEGQuantTable*       m_pQuantTablesThumbnail;                  ///< Pointer to Quantization tables
    EncoderOutInfo*       m_pEncodeOutParams;                       ///< Pointer to Encode out params
    EncoderOutInfo*       m_pEncodeOutParamsThumbnail;              ///< Pointer to Thumbnail Encode out params
    UINT32                m_quality;                                ///< Jpeg quality
    UINT32                m_qualityThumbnail;                       ///< Jpeg quality
    EXIFData              m_dataEXIF;                               ///< EXIF data
    CHAR                  m_makeEXIF[ExifMaxPropertyLength];        ///< JPEG EXIF make name
    CHAR                  m_modelEXIF[ExifMaxPropertyLength];       ///< JPEG EXIF model name
    Node*                 m_pNode;                                  ///< Pointer to the node
    BOOL                  m_bIsRealTime;                            ///< Flag that indicates real time or not
};

CAMX_NAMESPACE_END

#endif // CAMXJPEGEXIFPARAMS_H
